import types


def f1(self, x, y):
    print(x, y)

class Person:
    """A class representing a person."""
    # 限制实例可以添加的实例属性和实例方法
    # __slots__ = ("name", "age", "id", "f2")

    home = "Earth"
    def __init__(self):
        self.name = "John Doe"
        self.age = 30
        self.__id = 12345

    def __private_method(self):
        print("This is a private method.")

    def private_method_caller(self):
        self.__private_method()

    @property
    def eat(self):
        print(f"{self.name} is eating.")

    @classmethod
    def class_method(cls):
        print(f"This is a class method. Home: {cls.home}")

    @staticmethod
    def static_method():
        print("This is a static method.")

    f = f1

    @property
    def id(self):
        return self.__id

    @id.setter
    def id(self, value):
        self.__id = value


person = Person()
print(person.name)
print(person.age)
print(Person.home)
# person_eat = Person.eat
# person_eat(person)
# person.eat()

person.id = 12345
# print(person.id)
# del person.id
# print(person.id)
# print(Person.id)
Person.id = 0
# print(Person.id)
# print(person.id)
Person.class_method()
Person.static_method()
Person().f(1, 2)

# 添加实例方法
def f2(self, x, y):
    print(x, y)
    print(self.name)

# 直接将函数绑定到实例上，不用传递person这个示例就可以轻松调用
person.f2 = types.MethodType(f2, person)
person.f2(3, 4)

@classmethod
def f3(cls, x, y):
    print(x, y)
    print(cls.home)

@staticmethod
def f4(x, y):
    print(x, y)

Person.f3 = f3
Person.f4 = f4
Person.f3(5, 6)
Person.f4(7, 8)

# print(person.__id)
person.private_method_caller()

person.eat

print(person.id)
person.id = 12345
print(person.id)

# @perpety修饰的方法不能和变量同名

class YellowPerson(Person):
    def __init__(self):
       super().__init__()

    def eat(self):
        print("Yellow Person is eating.")

    def run(self):
       print("Yellow Person is running.")

class Student(Person):
    def __init__(self):
        super().__init__()

    def eat(self):
        print("Student is eating.")

class ChineseStudent(Student, YellowPerson):
    def __init__(self):
        super().__init__()

    def eat(self):
        print("Chinese Student is eating.")

cs = ChineseStudent()
cs.eat()
cs.run()
print(ChineseStudent.__mro__)

class MyError(Exception):
    def __init__(self, value):
       self.value = value

    def __str__(self):
       return self.value

try:
    # result = 1 / 0
    # raise TypeError("TypeError")
    # assert 1 == 2
    raise MyError("MyError")
except ZeroDivisionError as e:
    print(e)
except (RuntimeError, TypeError, NameError) as e:
    print(e)
except MyError as e:
    print(e)
except:
    print("Unknown error")
else:
    print("No error")
finally:
    print("End")

# with open("file.txt", "r") as f:
#     for line in f:
#         print(line)

import test.circle
from test.rectangle import *